﻿using System;
using System.ComponentModel;

using DevExpress.Xpo;
using DevExpress.Xpo.Metadata;
using DevExpress.Data.Filtering;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Security.Strategy;

namespace WaTP.Module.BusinessObjects
{
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("OrderCode")]
    public class TransferOrder : BaseObject
    {
        public TransferOrder(Session session)
            : base(session)
        {
            // This constructor is used when an object is loaded from a persistent storage.
            // Do not place any code here or place it only when the IsLoading property is false:
            // if (!IsLoading){
            //    It is now OK to place your initialization code here.
            // }
            // or as an alternative, move your initialization code into the AfterConstruction method.
        }
        private string orderCode;
        public string OrderCode {
            get {
                if( Category != null && Type != null && Department != null && StartDateTime != null)
                orderCode = Category.OrderID + Type.OrderTypeID + Department.DepartmentID + FormatDateTime(StartDateTime);
                return orderCode; }
            //set { SetPropertyValue("OrderCode", ref orderCode, value); }
        }
        private string subject;
        [RuleRequiredField(DefaultContexts.Save)]
        public string Subject {
            get { return subject; }
            set { SetPropertyValue("Subject", ref subject, value); }
        }
        private OrderCategory category;
        public OrderCategory Category {
            get { return category; }
            set { SetPropertyValue("Category", ref category, value); }
        }
        private OrderType type;
        [DataSourceProperty("Category.Types")]
        public OrderType Type {
            get { return type; }
            set { SetPropertyValue("Type", ref type, value); }
        }
        private Department department;
        public Department Department {
            get { return department; }
            set { SetPropertyValue("Department", ref department, value); }
        }
        [Persistent("StartDateTime"), ValueConverter(typeof(UtcDateTimeConverter))]
        protected DateTime startDateTime = DateTime.Now;
        [PersistentAlias("startDateTime")]
        [ModelDefault("EditMask", "G")]
        [ModelDefault("DisplayFormat", "{0:G}")]
        public DateTime StartDateTime {
            get { return startDateTime; }
            //set { SetPropertyValue("StartDateTime", ref startDateTime, value); }
        }
        internal virtual void UpdateCreatedOn()
        {
            UpdateCreatedOn(DateTime.Now);
        }
        internal virtual void UpdateCreatedOn(DateTime date)
        {
            startDateTime = date;
            Save();
        }
        protected override void OnChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnChanged(propertyName, oldValue, newValue);
            if (propertyName == "OrderCode")
            {
                UpdateCreatedOn();
            }
        }
        private DateTime endDateTime;
        public DateTime EndDateTime {
            get { return endDateTime; }
            set { SetPropertyValue("EndDateTime", ref endDateTime, value); }
        }

        //private bool approve;//Duyệt lệnh điều chuyển.
        //public bool Approve {
        //    get { return approve; }
        //    set { SetPropertyValue("Approve", ref approve, value); }
        //}
        private bool canceled;//Hủy lệnh điều chuyển.
        public bool Canceled {
            get { return canceled; }
            set { SetPropertyValue("Canceled", ref canceled, value); }
        }

        private int? checkDocument = null;//Check số lượng văn bản liên quan. 1- yêu cầu điều chuyển; 2- xác nhận yêu cầu; 3- Lệnh điều chuyển; 4. Phiếu xuất/nhập kho; 5. Phiếu giao/ nhận hàng.
        public int? CheckDocument {
            get {
                if (!IsLoading && !IsSaving && checkDocument == null) {
                    UpdateDocumentCount(false);
                }
                return checkDocument; }
            //set { SetPropertyValue("CheckDocument", ref checkDocument, value); }
        }
        //User
        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User
        {
            get { return user; }
            internal set { user = value; }
        }
        private string notes;

        public string Notes {
            get { return notes; }
            set { SetPropertyValue("Notes", ref notes, value); }
        }
        private TransferOrderStatus status;
        public TransferOrderStatus Status {
            get {
                if (Canceled == false)
                {
                    if (CheckDocument < 2)//Hạn chế ko cho user xóa attachment file.
                    {
                        status = TransferOrderStatus.InProgress;
                    }
                    else {
                        if (CheckDocument == 2)
                        {
                            //if (Approve == false)
                                status = TransferOrderStatus.WaitingForSomeoneElse;
                            //else
                            //    status = TransferOrderStatus.Approve;
                        }
                        else {
                            if (CheckDocument == 3) {
                                status = TransferOrderStatus.Approve;
                            }
                            else
                                if (CheckDocument == 5)
                                    status = TransferOrderStatus.Completed;
                        }
                    }
                }
                else
                    status = TransferOrderStatus.Cancel;       
                return status; }
            set { SetPropertyValue("Status", ref status, value); }
        }
        private TransferRequiredTicket ticket;
        [Association("TransferTicket-Orders")]
        public TransferRequiredTicket Ticket {
            get { return ticket; }
            set {
                TransferRequiredTicket oldTicket = ticket;
                SetPropertyValue("Ticket", ref ticket, value);
                if (!IsLoading && !IsSaving && oldTicket != ticket)
                {
                    oldTicket = oldTicket ?? ticket;
                    oldTicket.UpdateOrdersCount(true);
                    oldTicket.UpdateCompletedOrdersCount(true);
                }
            }
        }
        [Association("TransferOrder-Documents"), Aggregated]
        public XPCollection<Document> Documents {
            get { return GetCollection<Document>("Documents");}
        }
        [Association("TransferOrder-Activities")]
        public XPCollection<Activity> Activities {
            get { return GetCollection<Activity>("Activities");}
        }
        [Association("TransferOrder-WarehouseTotal1"), Aggregated]
        public XPCollection<WareHouseTotal1> Total1 {
            get { return GetCollection<WareHouseTotal1>("Total1");}
        }
        [Association("TransferOrder-WarehouseTotal2"), Aggregated]
        public XPCollection<WareHouseTotal2> Total2 {
            get { return GetCollection<WareHouseTotal2>("Total2");}
        }
        [Association("TransferOrder-WarehouseTotal3"), Aggregated]
        public XPCollection<WareHouseTotal3> Total3{
            get { return GetCollection<WareHouseTotal3>("Total3");}
        }
        [Association("TransferOrder-Shipped")]
        public XPCollection<Shipped>Ships{
            get { return GetCollection<Shipped>("Ships");}
        }
        private string FormatDateTime(DateTime date){
            string temp = null;
            string stringDate = date.ToString();
            for (int i = 0; i < stringDate.Length; i++) {
                if ((stringDate[i] != '/') && (stringDate[i] != '-') & (stringDate[i] != ':') && (stringDate[i] != ' ')) {
                    temp += stringDate[i].ToString(); 
                }
            }
                return temp;
        }

        public void UpdateDocumentCount(bool forceChangeEvents) {
            int? oldDocumentCount = checkDocument;
            checkDocument = Convert.ToInt32(Session.Evaluate<TransferOrder>(CriteriaOperator.Parse("Documents.Count"),
                CriteriaOperator.Parse("Oid=?", Oid)));
            if (forceChangeEvents)
                OnChanged("CheckDocument", oldDocumentCount, checkDocument);
        }
        protected override void OnLoaded()
        {
            Reset();
            base.OnLoaded();
        }
        private void Reset() {
            checkDocument = null;
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            Status = TransferOrderStatus.InProgress;
            // Place here your initialization code.
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
        }
    }
    public enum TransferOrderStatus {
        [ImageName("State_Task_InProgress")]
        InProgress,
        [ImageName("State_Task_WaitingForSomeoneElse")]
        WaitingForSomeoneElse,
        [ImageName("State_Validation_Valid")]
        Approve,
        [ImageName("State_Validation_Invalid")]
        Cancel,
        [ImageName("State_Task_Completed")]
        Completed
    }

    public class Document : BaseObject {
        public Document(Session session)
            : base(session) { }
        private string documentName;
        [RuleRequiredField(DefaultContexts.Save)]
        public string DocumentName {
            get { return documentName; }
            set { SetPropertyValue("DocumentName", ref documentName, value); }
        }
        private FileData attachmentFile;
        public FileData AttachmentFile {
            get { return attachmentFile; }
            set { SetPropertyValue("AttachmentFile", ref attachmentFile, value); }
        }
        [Persistent("CreateOn"), ValueConverter(typeof(UtcDateTimeConverter))]
        protected DateTime _CreateOn = DateTime.Now;
        [PersistentAlias("_CreateOn")]
        [ModelDefault("EditMask", "G")]
        [ModelDefault("DisplayFormat", "{0:G}")]
        public DateTime CreateOn {
            get { return _CreateOn; }
        }
        internal virtual void UpdateCreatedOn() {
            UpdateCreatedOn(DateTime.Now);
        }
        internal virtual void UpdateCreatedOn(DateTime date)
        {
            _CreateOn = date;
            Save();
        }
        protected override void OnChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnChanged(propertyName, oldValue, newValue);
            if (propertyName == "DocumentName") {
                UpdateCreatedOn();
            }
        }
        //User.
        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User {
            get { return user; }
            internal set { user = value; }
        }
        //TransferOrder.
        private TransferOrder transferOrder;
        [Association("TransferOrder-Documents")]
        public TransferOrder TransferOrder {
            get { return transferOrder; }
            set {
                TransferOrder oldOrder = transferOrder;
                SetPropertyValue("TransferOrder", ref transferOrder, value);
                if (!IsLoading && !IsSaving && oldOrder != transferOrder) {
                    oldOrder = oldOrder ?? transferOrder;
                    oldOrder.UpdateDocumentCount(true);
                }
            }
        }
        //QualityTest
        private QualityTest qualityTest;
        [Association("Quality-Documents")]
        public QualityTest QuanlityTest {
            get { return qualityTest; }
            set { SetPropertyValue("QuanlityTest", ref qualityTest, value); }
        }
        //CustomsFormality
        private CustomsFormality customsFormality;
        [Association("Formality-Documents")]
        public CustomsFormality CustomsFormality {
            get { return customsFormality; }
            set { SetPropertyValue("CustomsFormality", ref customsFormality, value); }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
        }

    }
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("DepartmentName")]
    public class Department : BaseObject {
        public Department(Session session)
            : base(session) { }
        private string departmentID;
        [RuleRequiredField(DefaultContexts.Save)]
        public string DepartmentID {
            get { return departmentID; }
            set { SetPropertyValue("DepartmentID", ref departmentID, value); }
        }
        private string departmentName;
        [RuleRequiredField(DefaultContexts.Save)]
        public string DepartmentName {
            get { return departmentName; }
            set { SetPropertyValue("DepartmentName", ref departmentName, value); }
        }
    }
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("OrderName")]
    public class OrderCategory : BaseObject {
        public OrderCategory(Session session)
            : base(session) { }
        private string orderName;
        [RuleRequiredField(DefaultContexts.Save)]
        public string OrderName {
            get { return orderName; }
            set { SetPropertyValue("OrderName", ref orderName, value); }
        }
        private string orderID;
        public string OrderID {
            get { return orderID; }
            set { SetPropertyValue("OrderID", ref orderID, value); }
        }
        [Association("Category-Types"), Aggregated]
        public XPCollection<OrderType> Types {
            get { return GetCollection<OrderType>("Types"); }
        }
    }
    [System.ComponentModel.DefaultProperty("OrderDetail")]
    public class OrderType : BaseObject {
        public OrderType(Session session)
            : base(session) { }
        private string orderTypeID;
        public string OrderTypeID {
            get { return orderTypeID; }
            set { SetPropertyValue("OrderTypeID", ref orderTypeID, value); }
        }
        private string orderDetail;
        public string OrderDetail {
            get { return orderDetail; }
            set { SetPropertyValue("OrderDetail", ref orderDetail, value); }
        }
        private OrderCategory category;
        [Association("Category-Types")]
        public OrderCategory Category {
            get { return category; }
            set { SetPropertyValue("Category", ref category, value); }
        }
    }
    [DefaultClassOptions]
    public class Shipped : BaseObject {
       public Shipped(Session session)
           : base(session) { }
       private Transport transport;
       [Association("Transport-Shipped")]
       public Transport Transport {
           get { return transport; }
           set { SetPropertyValue("Transport", ref transport, value); }
       }
       private string shippedCode;
       public string ShippedCode {
           get {
               shippedCode = "TCS-" + FormatDateTime(StartDateTime);
               return shippedCode;  }
           //set { SetPropertyValue("ShippedCode", ref shippedCode, value); }
       }
       private string truckNumber;//Số xe
       public string TruckNumber {
           get { return truckNumber; }
           set { SetPropertyValue("TruckNumber", ref truckNumber, value); }
       }
       private string capacity;//Trọng tải.
       public string Capacity {
           get { return capacity; }
           set { SetPropertyValue("Capacity", ref capacity, value); }
       }
        [Persistent("StartDateTime"), ValueConverter(typeof(UtcDateTimeConverter))]
       protected DateTime startDateTime = DateTime.Now;
        [PersistentAlias("startDateTime")]
        [ModelDefault("EditMask", "G")]
        [ModelDefault("DisplayFormat", "{0:G}")]
       public DateTime StartDateTime {
           get { return startDateTime; }
       }
        private string FormatDateTime(DateTime date)
        {
            string temp = null;
            string stringDate = date.ToString();
            for (int i = 0; i < stringDate.Length; i++)
            {
                if ((stringDate[i] != '/') && (stringDate[i] != '-') & (stringDate[i] != ':') && (stringDate[i] != ' '))
                {
                    temp += stringDate[i].ToString();
                }
            }
            return temp;
        }
       internal virtual void UpdateCreatedOn()
       {
           UpdateCreatedOn(DateTime.Now);
       }
       internal virtual void UpdateCreatedOn(DateTime date)
       {
           startDateTime = date;
           Save();
       }
       protected override void OnChanged(string propertyName, object oldValue, object newValue)
       {
           base.OnChanged(propertyName, oldValue, newValue);
           if (propertyName == "ShippedCode")
           {
               UpdateCreatedOn();
           }
       }
       private DateTime endDateTime;
       public DateTime EndDateTime {
           get { return endDateTime; }
           set { SetPropertyValue("EndDateTime", ref endDateTime, value); }
       }
       private string fromLocation;
       public string FromLocation {
           get { return fromLocation; }
           set { SetPropertyValue("FromLocation", ref fromLocation, value); }
       }
       private string toLocation;
       public string ToLocation {
           get { return toLocation; }
           set { SetPropertyValue("ToLocation", ref toLocation, value); }
       }
       private decimal cost;
       public decimal Cost {
           get { return cost; }
           set { SetPropertyValue("Cost", ref cost, value); }
       }
       private ShippedStatus status;
       public ShippedStatus Status {
           get { return status; }
           set { SetPropertyValue("Status", ref status, value); }
       }
        //User
        [Persistent("User")]
       private SecuritySystemUser user;
        [PersistentAlias("user")]
       public SecuritySystemUser User {
           get { return user; }
           internal set { user = value; }
       }

       private string notes;
       [Size(1024)]
       public string Notes {
           get { return notes; }
           set { SetPropertyValue("Notes", ref notes, value); }
       }
        [Association("TransferOrder-Shipped")]
       public XPCollection<TransferOrder> Orders {
           get { return GetCollection<TransferOrder>("Orders"); }
       }
       public override void AfterConstruction()
       {
           base.AfterConstruction();
           Status = ShippedStatus.NotStarted;
           user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
       }
   }

    public enum ShippedStatus {
        [ImageName("State_Task_NotStarted")]
        NotStarted,
        [ImageName("State_Task_InProgress")]
        InProgress,
        [ImageName("State_Task_Completed")]
        Completed,
        [ImageName("State_Validation_Invalid")]
        Cancel,
        [ImageName("State_Task_Deferred")]
        Deferred
    }
}
